﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Omniture.API;
using System.Windows.Forms;

namespace Omniture.Studio.Objects
{
	internal class FileHelper
	{
		public static string[] LoadDocumentDesign(OmnitureProject project, string fileName)
		{
			var errorList = new List<string>();
			var lines = LoadCSVFile(fileName);

			var index = 0;
			var isProcessingEvar = false;
			var isProcessingProp = false;
			var isProcessingEvent = false;
			var cache = new List<TrackItemBase>();
			foreach (string[] arr in lines)
			{
				//Ignore the header line
				if ((arr.Length >= 5) && (arr[0].ToLower() == "variable")
					&& (arr[1].ToLower() == "alias") && (arr[2].ToLower() == "description")
					&& (arr[3].ToLower() == "default") && (arr[4].ToLower() == "isrequired"))
				{
					//Do Nothing
				}
				else if ((arr.Length >= 1) && (arr[0].ToLower() == string.Empty))
				{
					isProcessingEvar = false;
					isProcessingProp = false;
					isProcessingEvent = false;
				}
				else if ((arr.Length >= 1) && (arr[0].ToLower() == "evar list"))
				{
					isProcessingEvar = true;
					isProcessingProp = false;
					isProcessingEvent = false;
				}
				else if ((arr.Length >= 1) && (arr[0].ToLower() == "prop list"))
				{
					isProcessingEvar = false;
					isProcessingProp = true;
					isProcessingEvent = false;
				}
				else if ((arr.Length >= 1) && (arr[0].ToLower() == "event list"))
				{
					isProcessingEvar = false;
					isProcessingProp = false;
					isProcessingEvent = true;
				}
				else if (isProcessingEvar)
				{
					if (arr.Length >= 5)
					{
						EVarItem item = new EVarItem(project.EVarList, 0);
						item.Alias = arr[1];
						item.Description = arr[2];
						item.DefaultValue = arr[3];
						string boolValue = arr[4];
						if (boolValue == string.Empty) boolValue = "false";
						item.IsRequired = bool.Parse(boolValue.ToLower());
						if (!TrackItemBase.ValidateName(arr[0]))
						{
							errorList.Add("The name '" + arr[0] + "' is invalid.");
						}
						else if (!item.ParentCollection.ParentItem.IsTrackItemUnique(arr[0], item))
						{
							errorList.Add("The name '" + arr[0] + "' is not unique.");
						}
						else
						{
							item.Name = arr[0];
							cache.Add(item);
						}
					}
					else
					{
						errorList.Add("Error on line " + index + ". The line does not have enough columns.");
					}

				}
				else if (isProcessingProp)
				{
					if (arr.Length >= 5)
					{
						PropItem item = new PropItem(project.PropList, 0);
						item.Alias = arr[1];
						item.Description = arr[2];
						item.DefaultValue = arr[3];
						string boolValue = arr[4];
						if (boolValue == string.Empty) boolValue = "false";
						item.IsRequired = bool.Parse(boolValue.ToLower());
						if (!TrackItemBase.ValidateName(arr[0]))
						{
							errorList.Add("The name '" + arr[0] + "' is invalid.");
						}
						else if (!item.ParentCollection.ParentItem.IsTrackItemUnique(arr[0], item))
						{
							errorList.Add("The name '" + arr[0] + "' is not unique.");
						}
						else
						{
							item.Name = arr[0];
							cache.Add(item);
						}
					}
					else
					{
						errorList.Add("Error on line " + index + ". The line does not have enough columns.");
					}
				}
				else if (isProcessingEvent)
				{
					if (arr.Length >= 3)
					{
						EventItem item = new EventItem(project.EventList, 0);
						item.Alias = arr[1];
						item.Description = arr[2];
						if (!TrackItemBase.ValidateName(arr[0]))
						{
							errorList.Add("The name '" + arr[0] + "' is invalid.");
						}
						else if (!item.ParentCollection.ParentItem.IsTrackItemUnique(arr[0], item))
						{
							errorList.Add("The name '" + arr[0] + "' is not unique.");
						}
						else
						{
							item.Name = arr[0];
							cache.Add(item);
						}
					}
					else
					{
						errorList.Add("Error on line " + index + ". The line does not have enough columns.");
					}
				}
				else
				{
					isProcessingEvar = false;
					isProcessingProp = false;
					isProcessingEvent = false;
				}

				index++;

			}

			//If there are no errors then process the changes
			if (errorList.Count == 0)
			{
				project.EVarList.Clear();
				project.PropList.Clear();
				project.EventList.Clear();
				foreach (TrackItemBase item in cache)
				{
					item.ParentCollection.Add(item);
				}
			}

			return errorList.ToArray();
		}

		public static string[] LoadTaggingSchema(OmnitureProject project, string fileName)
		{
			var errorList = new List<string>();
			var cache = new List<PageItem>();
			var lines = LoadCSVFile(fileName);
			var index = 0;
			var isProcessing = false;
			foreach (string[] arr in lines)
			{
				if (!isProcessing)
				{
					if ((arr.Length >= 6) && (arr[0].ToLower() == "url") && (arr[1].ToLower() == "page name")
						&& (arr[2].ToLower() == "channel") && (arr[3].ToLower() == "events")
						&& (arr[4].ToLower() == "props") && (arr[5].ToLower() == "evars"))
					{
						isProcessing = true;
					}
				}
				else
				{
					//We are processing this line
					if ((arr.Length >= 6))
					{
						string url = arr[0];
						string pageName = arr[1];
						string channel = arr[2];
						string events = arr[3].Replace(" ", string.Empty);
						string props = arr[4].Replace(" ", string.Empty);
						string evars = arr[5].Replace(" ", string.Empty);

						PageItem pageItem = new PageItem(project);
						pageItem.ChannelName = channel;
						pageItem.PageName = pageName;
						pageItem.PageURL = url;
						cache.Add(pageItem);

						int theValue;

						//Process events
						string[] arrEvents = events.Split(',');
						foreach (string k in arrEvents)
						{
							if (project.EventList.Contains(k))
								pageItem.EventList.NewItem(project.EventList[k]);
							else if (int.TryParse(k, out theValue) && project.EventList.Contains("event" + k)) //fallback for number only
								pageItem.EventList.NewItem(project.EventList["event" + k]);
						}

						//Process props
						string[] arrProps = events.Split(',');
						foreach (string k in arrProps)
						{
							if (project.PropList.Contains(k))
								pageItem.PropList.NewItem(project.PropList[k]);
							else if (int.TryParse(k, out theValue) && project.PropList.Contains("prop" + k)) //fallback for number only
								pageItem.PropList.NewItem(project.PropList["prop" + k]);
						}

						//Process evars
						string[] arrEvars = events.Split(',');
						foreach (string k in arrEvars)
						{
							if (project.EVarList.Contains(k))
								pageItem.EVarList.NewItem(project.EVarList[k]);
							else if (int.TryParse(k, out theValue) && project.EVarList.Contains("evar" + k)) //fallback for number only
								pageItem.EVarList.NewItem(project.EVarList["evar" + k]);
						}

					}
				}

				index++;
			}

			//If there are no error then reload the project
			if (errorList.Count == 0)
			{
				project.PageList.Clear();
				foreach (var cacheItem in cache)
				{
					var oldPage = project.PageList.FirstOrDefault(x => x.PageURL.ToLower() == cacheItem.PageURL.ToLower());
					if (oldPage == null)
					{
						project.PageList.AddRange(cache);
					}
					else
					{
						oldPage.ChannelName = cacheItem.ChannelName;
						oldPage.PageName = cacheItem.PageName;
					}
				}
				
			}

			return errorList.ToArray();
		}

		private static List<string[]> LoadCSVFile(string fileName)
		{
			var retval = new List<string[]>();

			var sr = File.OpenText(fileName);
			var textList = new List<string>();
			var index = 0;
			var lineText = string.Empty;
			while (!sr.EndOfStream)
			{
				var text = sr.ReadLine();
				lineText += text + "\n";
				var t2 = lineText.Replace("\"", string.Empty);
				if (((t2.Length - lineText.Length) % 2) == 0)
				{
					lineText = lineText.TrimEnd('\n'); //take off last line return
					textList.Add(lineText);
					retval.Add(BreakColumns(lineText));
					var inner = new List<string>();

					lineText = string.Empty;
				}
				index++;
			}

			return retval;

		}

		private static string[] BreakColumns(string text)
		{
			var list = new List<string>();
			var s = string.Empty;
			var inside = false;
			for (int ii = 0; ii < text.Length; ii++)
			{
				if ((text[ii] == ',') && !inside)
				{
					list.Add(s);
					s = string.Empty;
				}
				else if ((text[ii] == '"') && !inside)
				{
					inside = true;
				}
				else if ((text[ii] == '"') && inside)
				{
					inside = false;
				}
				else
				{
					s += text[ii];
				}

			}
			list.Add(s);

			return list.ToArray();
		}

	}
}